#include "app_device.h"
#include "app_modbus.h"
#include "app_mqtt.h"
#include "app_pool.h"
#include "app_buffer.h"
#include "app_message.h"
#include "app_common.h"
#include "string.h"
#include "cJSON.h"
#include "stdio.h"
#include "log.h"

static app_buffer_t *up_buffer;
static app_buffer_t *down_buffer;

static int device_id_to_check[MAX_DEVICE_NUM];
static int device_num=0;

static pthread_t device_scan_thread;

/**
 * @brief 设备模块初始化
 * // mqtt初始化
 * // 线程池的初始化
 * // 缓冲区的初始化 2个
 * // modbus初始化
 * 
 */
void app_device_init(char *modbus_dev_file_name)
{

    app_mqtt_init();
    app_pool_init();
    up_buffer= app_buffer_init(1024);
    down_buffer= app_buffer_init(1024);
    app_modbus_init(modbus_dev_file_name);

}

/**
 * @brief 给设备清单增加一个设备id
 */
static void add_device_id(int device_id)
{
    device_id_to_check[device_num]= device_id;
    device_num++;
    printf("cur device_list:");
    for (size_t i = 0; i < device_num; i++)
    {
         printf("%d ",   device_id_to_check[i]);
    }
    printf("\n");
}


/**
 * @brief 下行通路  下半部分  线程：线程池
 *   1  从下行缓冲区读取字节数组
     2  从字节数组中提取值
     3  发送给modbus
     4  把设备id加入设备监控清单中
 */
static int down2_sendModbus(void *arg)
{
    //  *   1  从下行缓冲区读取字节数组
    uint8_t  buff[100];
    int size= app_buffer_read(down_buffer, buff, 100);
    //  2  从字节数组中提取值
    int slave_id= buff[0];

    // 把uint8_t 字节  转为 寄存器数组
    uint16_t reg_buff[4];
    memcpy(reg_buff, buff+1, size-1);

    //  3  发送给modbus
    app_modbus_writeHoldReg(slave_id, 0, (size-1)/2,reg_buff );
  
    //  4  把设备id加入设备监控清单中
    add_device_id(slave_id);

    return 0;
}

/**
 * @brief 下行通路  上半部分  线程：mqtt客户端扫描线程 
 *   1  json 转为 字节数组 
 *   2  字节数组写入下行缓冲区
 *   3  提交任务给线程池
 */
static int down1_mqtt_callback(char *message)
{   
    //  1  json 转为 字节数组 
    uint8_t  buff[100];
     int size= app_message_jsonToChar( message, buff, 100 );
    // *   2  字节数组写入下行缓冲区
     app_buffer_write(down_buffer,  buff, size);
   // 3  提交任务给线程池
    app_pool_submitTask(down2_sendModbus, NULL);

    return 0;
}

/**
 * @brief 删除设备

 */
void remvoe_device(int device_id)
{
    for(int i=0; i<device_num; i++)
    {
        if(device_id_to_check[i]==device_id)
        {
            memmove(device_id_to_check+i, device_id_to_check+i+1, device_num-i-1);
            device_num--;
            break;
        }
    }
    printf("cur device_list:");
    for (size_t i = 0; i < device_num; i++)
    {
         printf("%d ",   device_id_to_check[i]);
    }
    printf("\n");
}


/**
 * @brief 上行通路  下半部分  线程：线程池
 *   1  从上行缓冲区读取字节数组
 *   2  把字节数组转为json
 *   3  发送给mqtt
 */
static int up2_sendMqtt(void *arg)
{
//  *   1  从上行缓冲区读取字节数组
    uint8_t  buff[100];
    int size= app_buffer_read(up_buffer, buff, 100);
 
    int device_id= buff[0];
    bool motor_status= buff[5];

//  *   2  把字节数组转为json
    char *json= app_message_charToJson(buff, size);
//  *   3  发送给mqtt
    app_mqtt_send(json);
 
    // 注意是否堆内存
    cJSON_free(json);

    //4  检查设备的状态，如果为停机，则从扫描清单中去除
    if(!motor_status )
    {
        remvoe_device(device_id);
    }

    return 0;
}


/**
 * @brief 上行通路  上半部分  线程：设备模块设备扫描线程
 *   1  从modbus中读取数据
 *   2  提取数据 写入上行缓冲区
 *   3  提交任务给线程池
 */
void up1_getDataFromModbus(int device_id)
{
//      *   1  从modbus中读取数据
   uint16_t reg_buff[3];
   int ret= app_modbus_readInputReg(device_id, 0, 3, reg_buff);
   if(ret<0)
   {
      return ;
   }
  //  *   2  提取数据 写入上行缓冲区
   uint8_t  buff[100];
   buff[0]= device_id;
   memcpy(buff+1, reg_buff, 6);

   app_buffer_write(up_buffer, buff, 7);
   //  *   3  提交任务给线程池
   app_pool_submitTask(up2_sendMqtt, NULL);

   
    
}


/**
 * @brief 检查设备清单中有哪些设备 ，对这些设备进行数据上报（数据上行通路)
 */
static void *device_scan(void *arg)
{ 

    while(1)
    {
        for(int i=0; i<device_num; i++)
        {
            int device_id= device_id_to_check[i];
            up1_getDataFromModbus(device_id);
            usleep(50*1000);
        }
        sleep(1);
    }
    return NULL;
}

/**
 * @brief 设备模块的启动
 * 下行通路的启动 ： 向mqtt注册回调函数 
 * 上行通路的启动 ： 启动对设备清单的扫描线程
 */
void app_device_start(void)
{
    //下行通路的启动 ： 向mqtt注册回调函数 
    app_mqtt_register_callback(down1_mqtt_callback);
    //  上行通路的启动 ： 启动对设备清单的扫描线程
    pthread_create(&device_scan_thread, NULL, device_scan, NULL);


}



/**
 * @brief 设备模块的销毁
 *  * //设备扫描线程的销毁  
 *  * // mqtt销毁
 * // 线程池的销毁
 * // 缓冲区的销毁 2个
 * // modbus销毁

 */
void app_device_destroy(void)
{
//  *  * //设备扫描线程的销毁  
    pthread_cancel(device_scan_thread);
    pthread_join(device_scan_thread, NULL);
//  * // modbus销毁
    app_modbus_destroy();

//  * // 线程池的销毁
    app_pool_destroy();
//  *  * // mqtt销毁
    app_mqtt_destroy();

//  * // 缓冲区的销毁 2个
    app_buffer_destroy(up_buffer);
    app_buffer_destroy(down_buffer);

}